package _1DynamicArray.src;

import java.util.Arrays;
import java.util.Objects;

public class ArrayListDemo {

    // 存储数据的数组
    private String[] data;
    // 元素的实际个数
    private int size;

    // 定义无参的构造方法
    public ArrayListDemo(){
        data = new String[10];
    }

    // 定义有参的构造方法
    public ArrayListDemo(int len){
        // 判断参数是否合法
        if (len < 0) throw new IllegalArgumentException();

        data = new String[len];
    }

    /**
     * 添加元素方法
     */
    public void add(String str){
        // 判断是否需要扩容
        if (size == data.length){
            grow();
        }
        data[size++] = str;
    }

    /**
     * 数组扩容方法
     */
    private void grow() {
        if (data.length <= 1)
            data = Arrays.copyOf(data,data.length + 1);
        else
            data = Arrays.copyOf(data,data.length + (data.length >> 1));
    }

    /**
     * 插入元素
     * @param index  要插入的索引
     * @param str    要插入的数据
     */
    public void add(int index,String str){
        // 判断索引是否越界
        if (index < 0 || index > size) throw new IndexOutOfBoundsException("数组越界了");
        // 判断是否需要扩容
        if (size == data.length) grow();

        // 插入元素
        // 方式一:
        // 其实就是将数据统一向后挪动一位，然后腾出来的那一位赋值要插入的数据即可
//        for (int i = size - 1; i >= index;i--){
//            data[i + 1] = data[i];
//        }
        // 方式二:
        // 参数一:要拷贝的数组
        // 参数二:要拷贝的数组的起始索引
        // 参数三：要拷贝到的数组
        // 参数四:要拷贝到的数组的起始索引
        // 参数五：要拷贝的数据的长度
        System.arraycopy(data,index,data,index+1,size - index);
        data[index] = str;

        // 实际元素个数 + 1
        size++;
    }

    /**
     * 删除指定索引处的元素
     * @param index
     */
    public void remove(int index){
        // 判断索引是否越界
        out(index);

        // 删除元素就是将后面的元素统一向前挪动一位
        // 方式一:
//        for (int i = index;i < size - 1;i++){
//            data[i] = data[i + 1];
//        }
        // 方式二:
        System.arraycopy(data,index + 1,data,index,size - index - 1);
        // 实际元素个数-1
        size--;
        // 最后一位设置为null
        data[size] = null;
    }

    private void out(int index) {
        if (index < 0 || index >= size) throw new IndexOutOfBoundsException();
    }

    /**
     * 获取指定元素首次出现的索引
     * @param str
     * @return
     */
    public int indexOf(String str){
        for (int i = 0; i < size; i++) {
//            if (str == data[i] || (str != null && str.equals(data[i]))){
//
//            }
            if (Objects.equals(str,data[i])){
                return i;
            }
        }
        return -1;
    }

    /**
     * 删除指定的元素
     * @param str  要删除的元素
     */
    public void remove(String str){
        int i = indexOf(str);
        // 找到了元素就删除
        if (i != -1) remove(i);
    }

    /**
     * 清空集合
     */
    public void clear(){
        data = new String[10];
        size = 0;
    }

    /**
     * 判断是否包含指定的元素
     * @param str  指定的元素
     * @return  true包含    false不包含
     */
    public boolean contains(String str){
        return indexOf(str) != -1;
    }

    /**
     * 获取指定索引处的元素
     * @param index  指定索引
     * @return 元素
     */
    public String get(int index){
        // 判断索引是否越界
        out(index);
        return data[index];
    }

    /**
     * 判断集合是否为空
     * @return true 为空  false 不为空
     */
    public boolean isEmpty(){
        return size == 0;
    }

    /**
     * 替换元素
     */
    public void set(int index,String str){
        // 判断是否越界
        out(index);
        data[index] = str;
    }

    // 获取元素个数
    public int size(){
        return size;
    }

    public ArrayListDemo subList(int fromIndex,int toIndex){
        // 判断索引是否越界
        out(fromIndex);
        out(toIndex);
        // 判断参数是否合法
        if (fromIndex > toIndex) throw new IllegalArgumentException();

        // 创建新的列表
        ArrayListDemo sublist = new ArrayListDemo(toIndex - fromIndex);
        System.arraycopy(this.data,fromIndex,sublist.data,0,toIndex - fromIndex);
        // 设置列表实际元素个数
        sublist.size = toIndex - fromIndex;
        return sublist;
    }

    @Override
    public String toString() {
//        [1, 2, 3]
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = 0; i < size; i++) {
            if (i != size - 1){
                stringBuilder.append(data[i]).append(", ");
            }else {
                stringBuilder.append(data[i]);
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}